package cn.com.acca.ma.dao.impl;

import cn.com.acca.ma.common.util.*;
import cn.com.acca.ma.constant.FilterMethod;
import cn.com.acca.ma.enumeration.ExchangeBoardInfo;
import cn.com.acca.ma.jpa.impl.FindCodeAndMaxDateAndLastClosePriceGroupByCodeWorkImpl;
import cn.com.acca.ma.model.StockTransactionData;

import java.io.File;
import java.io.FileReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.*;
import java.util.*;
import java.util.Date;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import cn.com.acca.ma.model.StockTransactionDataAll;
import cn.com.acca.ma.pojo.*;
import oracle.jdbc.OracleConnection;

import cn.com.acca.ma.dao.StockTransactionDataDao;
import cn.com.acca.ma.enumeration.UpDown;
import cn.com.acca.ma.jpa.util.JpaUtil;
import cn.com.acca.ma.model.StockInfo;
import cn.com.acca.ma.model.StockMovingAverage;
import oracle.jdbc.OracleTypes;
import oracle.sql.*;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;

public class StockTransactionDataDaoImpl extends BaseDaoImpl<StockTransactionDataDaoImpl> implements
        StockTransactionDataDao {

    public StockTransactionDataDaoImpl() {
        super();
    }

    /**
     * 根据股票代码和日期，查找StockTransactionDataAll类型对象
     *
     * @param code
     * @param date
     * @return
     */
    public StockTransactionDataAll findByCodeAndDate(String code, Date date) {
        logger.info("开始根据code【" + code + "】和date【" + date + "】查找StockTransactionData对象");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        try {
            String queryString = "select t from StockTransactionDataAll t where t.code=? and t.date=?";
            Query query = em.createQuery(queryString);
            query.setParameter(1, code);
            query.setParameter(2, date);
            StockTransactionDataAll stockTransactionDataAll = (StockTransactionDataAll) query.getSingleResult();

            return stockTransactionDataAll;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        } finally {
            em.getTransaction().commit();
            em.close();
        }
    }

    /**
     * 根据股票代码和日期，查找上一个交易日的StockTransactionData类型对象
     *
     * @param code
     * @param date
     * @return
     */
    public StockTransactionData findLastByCodeAndDate(String code, Date date) {
        logger.info("开始根据code【" + code + "】和date【" + date + "】查找上一个交易日的StockTransactionData类型对象");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        try {
            String queryString = "select * from (select * from stock_transaction_data_all t where t.code_=? and t.date_<=? order by t.date_ desc) t2 where rownum<=1";
            Query query = em.createNativeQuery(queryString);
            query.setParameter(1, code);
            query.setParameter(2, date);
            query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
            Map map = (Map) query.getSingleResult();
            StockTransactionData stockTransactionData = ModelConverter.mapToStockTransactionData(map);

            return stockTransactionData;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            em.getTransaction().commit();
            em.close();
        }
    }

    /**
     * 查找某只股票开始时间和结束时间之内的最大收盘价
     *
     * @param stockCode
     * @param beginDate
     * @param endDate
     * @return
     */
    public BigDecimal findMaxClosePriceBetweenDate(String stockCode, String beginDate, String endDate) {
        logger.info("查找某只股票【" + stockCode + "】，开始时间【" + beginDate + "】和结束时间【" + endDate + "】之内的最大收盘价");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select max(t.closePrice) from StockTransactionDataAll t " +
                "where t.code=? and t.date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd')";
        Query query = em.createQuery(queryString);
        query.setParameter(1, stockCode);
        query.setParameter(2, beginDate);
        query.setParameter(3, endDate);
        BigDecimal maxClosePrice = (BigDecimal) query.getSingleResult();

        em.getTransaction().commit();
        em.close();

        return maxClosePrice;
    }

    /**
     * 查找某只股票开始时间和结束时间之内的最小收盘价
     *
     * @param stockCode
     * @param beginDate
     * @param endDate
     * @return
     */
    public BigDecimal findMinClosePriceBetweenDate(String stockCode, String beginDate, String endDate) {
        logger.info("查找某只股票【" + stockCode + "】，开始时间【" + beginDate + "】和结束时间【" + endDate + "】之内的最小收盘价");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select min(t.closePrice) from StockTransactionDataAll t " +
                "where t.code=? and t.date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd')";
        Query query = em.createQuery(queryString);
        query.setParameter(1, stockCode);
        query.setParameter(2, beginDate);
        query.setParameter(3, endDate);
        BigDecimal maxClosePrice = (BigDecimal) query.getSingleResult();

        em.getTransaction().commit();
        em.close();

        return maxClosePrice;
    }

    /**
     * 查找某只股票开始时间和结束时间之内的最大最高价
     *
     * @param stockCode
     * @param beginDate
     * @param endDate
     * @return
     */
    public BigDecimal findMaxHighestPriceBetweenDate(String stockCode, String beginDate, String endDate) {
        logger.info("查找某只股票【" + stockCode + "】，开始时间【" + beginDate + "】和结束时间【" + endDate + "】之内的最大最高价");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select max(t.highestPrice) from StockTransactionDataAll t " +
                "where t.code=? and t.date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd')";
        Query query = em.createQuery(queryString);
        query.setParameter(1, stockCode);
        query.setParameter(2, beginDate);
        query.setParameter(3, endDate);
        BigDecimal maxClosePrice = (BigDecimal) query.getSingleResult();

        em.getTransaction().commit();
        em.close();

        return maxClosePrice;
    }

    /**
     * 查找某只股票开始时间和结束时间之内的最小最低价
     *
     * @param stockCode
     * @param beginDate
     * @param endDate
     * @return
     */
    public BigDecimal findMinLowestPriceBetweenDate(String stockCode, String beginDate, String endDate) {
        logger.info("查找某只股票【" + stockCode + "】，开始时间【" + beginDate + "】和结束时间【" + endDate + "】之内的最小最低价");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select min(t.lowestPrice) from StockTransactionDataAll t " +
                "where t.code=? and t.date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd')";
        Query query = em.createQuery(queryString);
        query.setParameter(1, stockCode);
        query.setParameter(2, beginDate);
        query.setParameter(3, endDate);
        BigDecimal maxClosePrice = (BigDecimal) query.getSingleResult();

        em.getTransaction().commit();
        em.close();

        return maxClosePrice;
    }

    /**
     * 判断某只股票在某个时间区间内是否除权了。如果出现除权，则返回1；否则返回-1
     *
     * @param stockCode
     * @param beginDate
     * @param endDate
     * @return
     */
    @Override
    public Integer stockXR(String stockCode, String beginDate, String endDate) {
        logger.info("判断某只股票【" + stockCode + "】在某个时间区间【" + beginDate + "】【" + endDate + "】内是否除权了");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        StringBuilder sql = new StringBuilder("call FNC_STOCK_XR(:p_stock_code, :p_begin_date, :p_end_date)");
        Query query = em.createNativeQuery(sql.toString());
        query.setParameter(1, stockCode);
        query.setParameter(2, beginDate);
        query.setParameter(3, endDate);
        Integer result = (Integer) query.getSingleResult();

        em.getTransaction().commit();
        em.close();

        return result;
    }

    /**
     * 根据code查找StockTransactionData对象中最大的日期
     *
     * @param code
     * @return
     */
    public Date findMaxDateByCode(String code) {
        logger.info("开始根据code【" + code + "】查找StockTransactionData对象中最大的日期");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select max(t.date) from StockTransactionData t where t.code=?";
        Query query = em.createQuery(queryString);
        query.setParameter(1, code);
        Date date = (Date) query.getSingleResult();

        em.getTransaction().commit();
        em.close();

        return date;
    }

    /**
     * 根据code和date，查找某只股票最后一个交易日的close_price根据code和date，查找某只股票最后一个交易日的close_price
     *
     * @param multithreading
     * @param code
     * @param date
     * @return
     */
    public BigDecimal findLastClosePriceByCodeAndDate(boolean multithreading, String code, String date) {
        logger.info("开始根据code【" + code + "】查找某只股票最后一个交易日的close_price");

        EntityManager multithreadingEntityManager = null;
        String sqlString = "select t2.close_price from ( "
                + "select t1.close_price from stock_transaction_data_all t1 where t1.code_=? and t1.date_<to_date(?, 'yyyy-mm-dd') order by t1.date_ desc ) t2 "
                + "where rownum<=1";
        Query query;
        if (multithreading) {
            multithreadingEntityManager = JpaUtil.newEntityManager();
            multithreadingEntityManager.getTransaction().begin();
            query = multithreadingEntityManager.createNativeQuery(sqlString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sqlString);
        }

        query.setParameter(1, code);
        query.setParameter(2, date);

        if (null != multithreadingEntityManager) {
            if (query.getResultList().size() == 0) {
                logger.warn("stock_transaction_data表中没有代码为【" + code + "】的股票的交易记录");
                multithreadingEntityManager.getTransaction().commit();
                multithreadingEntityManager.close();

                return null;
            } else {
                BigDecimal lastClosePrice = (BigDecimal) query.getSingleResult();

                multithreadingEntityManager.getTransaction().commit();
                multithreadingEntityManager.close();

                return lastClosePrice;
            }
        } else {
            if (query.getResultList().size() == 0) {
                logger.warn("stock_transaction_data表中没有代码为【" + code + "】的股票的交易记录");
                em.getTransaction().commit();
                em.close();

                return null;
            } else {
                BigDecimal lastClosePrice = (BigDecimal) query.getSingleResult();

                em.getTransaction().commit();
                em.close();

                return lastClosePrice;
            }
        }
    }

    /**
     * 某一只股票，在某一日，120均线是否不单调递减，数据库里查119条+currentClosePrice。true表示是，false表示否
     *
     * @param stockCode
     * @param currentClosePrice
     * @param date
     * @return
     */
    @Override
    public Boolean isMa120NotDecreasing(String stockCode, BigDecimal currentClosePrice, String date) {
        logger.info("某一只股票，120均线是否不单调递减，数据库里查119条+currentClosePrice。true表示是，false表示否");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String currentQueryString = "select round((sum(t1.close_price) + ?)/120, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=119";
        Query currentQuery = em.createNativeQuery(currentQueryString);
        currentQuery.setParameter(1, currentClosePrice);
        currentQuery.setParameter(2, stockCode);
        currentQuery.setParameter(3, date);
        BigDecimal currentMa120 = (BigDecimal) currentQuery.getSingleResult();

        String previousQueryString = "select round(sum(t1.close_price)/120, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=120";
        Query previousQuery = em.createNativeQuery(previousQueryString);
        previousQuery.setParameter(1, stockCode);
        previousQuery.setParameter(2, date);
        BigDecimal previousMa120 = (BigDecimal) previousQuery.getSingleResult();

        em.getTransaction().commit();
        em.close();

        if (currentMa120.compareTo(previousMa120) == -1) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 某一只股票，在某一日，250均线是否不单调递减，数据库里查249条+currentClosePrice。true表示是，false表示否
     *
     * @param stockCode
     * @param currentClosePrice
     * @param date
     * @return
     */
    @Override
    public Boolean isMa250NotDecreasing(String stockCode, BigDecimal currentClosePrice, String date) {
        logger.info("某一只股票，250均线是否不单调递减，数据库里查119条+currentClosePrice。true表示是，false表示否");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String currentQueryString = "select round((sum(t1.close_price) + ?)/250, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=249";
        Query currentQuery = em.createNativeQuery(currentQueryString);
        currentQuery.setParameter(1, currentClosePrice);
        currentQuery.setParameter(2, stockCode);
        currentQuery.setParameter(3, date);
        BigDecimal currentMa250 = (BigDecimal) currentQuery.getSingleResult();

        String previousQueryString = "select round(sum(t1.close_price)/250, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=250";
        Query previousQuery = em.createNativeQuery(previousQueryString);
        previousQuery.setParameter(1, stockCode);
        previousQuery.setParameter(2, date);
        BigDecimal previousMa250 = (BigDecimal) previousQuery.getSingleResult();

        em.getTransaction().commit();
        em.close();

        if (currentMa250.compareTo(previousMa250) == -1) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 某一只股票，在某一日，120均线是否不单调递增数据库里查119条+currentClosePrice。true表示是，false表示否
     *
     * @param stockCode
     * @param currentClosePrice
     * @param date
     * @return
     */
    @Override
    public Boolean isMa120NotIncreasing(String stockCode, BigDecimal currentClosePrice, String date) {
        logger.info("某一只股票，120均线是否不单调递增，数据库里查119条+currentClosePrice。true表示是，false表示否");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String currentQueryString = "select round((sum(t1.close_price) + ?)/120, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=119";
        Query currentQuery = em.createNativeQuery(currentQueryString);
        currentQuery.setParameter(1, currentClosePrice);
        currentQuery.setParameter(2, stockCode);
        currentQuery.setParameter(3, date);
        BigDecimal currentMa120 = (BigDecimal) currentQuery.getSingleResult();

        String previousQueryString = "select round(sum(t1.close_price)/120, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=120";
        Query previousQuery = em.createNativeQuery(previousQueryString);
        previousQuery.setParameter(1, stockCode);
        previousQuery.setParameter(2, date);
        BigDecimal previousMa120 = (BigDecimal) previousQuery.getSingleResult();

        em.getTransaction().commit();
        em.close();

        if (previousMa120.compareTo(currentMa120) == -1) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 某一只股票，在某一日，250均线是否不单调递增，数据库里查249条+currentClosePrice。true表示是，false表示否
     *
     * @param stockCode
     * @param currentClosePrice
     * @param date
     * @return
     */
    @Override
    public Boolean isMa250NotIncreasing(String stockCode, BigDecimal currentClosePrice, String date) {
        logger.info("某一只股票，250均线是否不单调递增，数据库里查119条+currentClosePrice。true表示是，false表示否");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String currentQueryString = "select round((sum(t1.close_price) + ?)/250, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=249";
        Query currentQuery = em.createNativeQuery(currentQueryString);
        currentQuery.setParameter(1, currentClosePrice);
        currentQuery.setParameter(2, stockCode);
        currentQuery.setParameter(3, date);
        BigDecimal currentMa250 = (BigDecimal) currentQuery.getSingleResult();

        String previousQueryString = "select round(sum(t1.close_price)/250, 2) from (select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') order by t.date_ desc) t1 where rownum<=250";
        Query previousQuery = em.createNativeQuery(previousQueryString);
        previousQuery.setParameter(1, stockCode);
        previousQuery.setParameter(2, date);
        BigDecimal previousMa250 = (BigDecimal) previousQuery.getSingleResult();

        em.getTransaction().commit();
        em.close();

        if (previousMa250.compareTo(currentMa250) == -1) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 查找所有股票某一日的前收盘
     *
     * @param date
     * @return
     */
    public List findLastClosePrice(Date date) {
        logger.info("查找所有股票某一日【" + DateUtil.dateToString(date) + "】的前收盘");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select t1.code_ code, "
                + "       (select * from ("
                + "         	select t.close_price from stock_transaction_data_all t "
                + "         	where t.date_<? and t.code_=t1.code_ order by t.date_ desc "
                + "       		) t3 "
                + "		   where rownum<=1) lastClosePrice "
                + " from stock_transaction_data_all t1 "
                + "group by t1.code_";
        Query query = em.createNativeQuery(queryString);
        query.setParameter(1, date);
        List list = query.getResultList();

        em.getTransaction().commit();
        em.close();
        return list;
    }

    /**
     * 查找turnover_rate、turnover、total_market_value、circulation_market_value字段为空的记录
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public List<StockTransactionData> findByTurnoverRateNullOrTurnoverNullOrTotalMarketValueNullOrCirculationMarketValueNull(String beginDate, String endDate) {
        logger.info("查找turnover_rate、turnover、total_market_value、circulation_market_value字段为空的记录");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select t from StockTransactionData t "
                + "where (t.turnoverRate is null or t.turnover is null or t.totalMarketValue is null "
                + "or t.circulationMarketValue is null) and t.date between to_date(?, 'yyyy-mm-dd') "
                + "and to_date(?, 'yyyy-mm-dd')";
        Query query = em.createQuery(queryString);
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        List<StockTransactionData> list = query.getResultList();

        em.getTransaction().commit();
        em.close();
        return list;
    }

    /**
     * 根据code进行分组，查找每只股票的最后交易日期和最后的收盘价
     *
     * @return
     */
    public List findCodeAndMaxDateAndLastClosePriceGroupByCode() {
        logger.info("开始根据code进行分组，查找每只股票的最后交易日期和最后的收盘价");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select t.code_ code, "
                + "       max(t.date_) maxDate, "
                + "       (select t2.close_price "
                + "         from (select t1.close_price from stock_transaction_data t1 where t1.code_ = t.code_ order by t1.date_ desc) t2 "
                + "         where rownum <= 1) closePrice "
                + "from stock_transaction_data t "
                + "group by t.code_";

        FindCodeAndMaxDateAndLastClosePriceGroupByCodeWorkImpl workImpl = new FindCodeAndMaxDateAndLastClosePriceGroupByCodeWorkImpl(queryString);
        Session session = em.unwrap(Session.class);
        session.doWork(workImpl);
        ResultSet resultSet = workImpl.getResultSet();
        List list = ResultSetUtil.convertList(resultSet);

        // 由于使用jpa的方式太慢了，所以此处改用jdbc
//		Query query = em.createNativeQuery(queryString);
//		List list = query.getResultList();

        em.getTransaction().commit();
        em.close();

        return list;
    }

    /**
     * 将从网络中（或.json文件中）读取的数据写入到表STOCK_TRANSACTION_DATA中。
     *
     * @param stockTransactionDataList
     */
    public synchronized void writeStockTransactionDataList(List<StockTransactionData> stockTransactionDataList) {
        logger.debug("开始向表stock_transaction_data中插入数据");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        for (int i = 0; null != stockTransactionDataList
                && i < stockTransactionDataList.size(); i++) {
            StockTransactionData stockTransactionData = stockTransactionDataList.get(i);

            em.persist(stockTransactionData);

////			Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_STOCK_TRANSACTION_DATA(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
//			Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_STOCK_TRANSACTION_DATA(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
//			query.setParameter(1, stockTransactionData.getDate());
////			query.setParameter(1, stockTransactionData.getCode());
//			query.setParameter(2, stockTransactionData.getOpenPrice());
//			query.setParameter(3, stockTransactionData.getClosePrice());
//			query.setParameter(4, stockTransactionData.getHighestPrice());
//			query.setParameter(5, stockTransactionData.getLowestPrice());
//			query.setParameter(6, stockTransactionData.getChangeAmount());
//			query.setParameter(7, stockTransactionData.getChangeRange());
//			query.setParameter(8, stockTransactionData.getTurnoverRate());
//			query.setParameter(9, stockTransactionData.getVolume());
//			query.setParameter(10, stockTransactionData.getTurnover());
//			query.setParameter(11, stockTransactionData.getTotalMarketValue());
//			query.setParameter(12, stockTransactionData.getCirculationMarketValue());
//			query.executeUpdate();
        }
        em.getTransaction().commit();
        em.close();
    }

    /**
     * 将从网络中读取数据，更新STOCK_TRANSACTION_DATA表中的数据。
     *
     * @param stockTransactionData
     */
    public synchronized void updateStockTransactionData(StockTransactionData stockTransactionData) {
        logger.info("开始更新STOCK_TRANSACTION_DATA表中的数据");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        em.merge(stockTransactionData);
        em.getTransaction().commit();
        em.close();
    }

    /**
     * 从表STOCK_INFO中读取全部数据
     *
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public List<StockInfo> readStockInfo() {
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createQuery("select t from StockInfo t");
        List list = query.getResultList();
        em.getTransaction().commit();
        em.close();
        return list;
    }

    /*********************************************************************************************************************
     *
     * 							从网络上获取数据，存储在.json文件中；然后再解析文件，并插入到数据库中
     *
     *********************************************************************************************************************/
    /**
     * 将.json文件中的数据插入数据库
     */
    public void insertAllRecordsFromJson(List<StockTransactionData> stockTransactionDataList) {
        this.writeStockTransactionDataList(stockTransactionDataList);
    }

    /*********************************************************************************************************************
     *
     * 									                             更新每天的数据
     *
     *********************************************************************************************************************/
    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的FIVE，TEN，TWENTY，SIXTY和ONE_HUNDRED_TWENTY字段
     *
     * @param multithreading
     * @param date
     */
    public void writeMovingAverageByDate(boolean multithreading, String date) {
        logger.info("开始更新stock_transaction_data表中date_字段为【" + date
                + "】的记录的ma5，ma10，ma20，ma60、ma120和ma250字段");

        EntityManager multithreadingEntityManager = null;
        String sqlString = "{call pkg_stock_transaction_data.Write_Moving_Average_By_Date(?)}";
        Query query;
        if (multithreading) {
            multithreadingEntityManager = JpaUtil.newEntityManager();
            multithreadingEntityManager.getTransaction().begin();
            query = multithreadingEntityManager.createNativeQuery(sqlString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sqlString);
        }

        query.setParameter(1, date);
        query.executeUpdate();

        if (null != multithreadingEntityManager) {
            multithreadingEntityManager.getTransaction().commit();
            multithreadingEntityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中date_字段为【" + date
                + "】的记录的ma5，ma10，ma20，ma60、ma120和ma250字段完成");
    }

    /**
     * 按照日期，计算所有股票的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段
     *
     * @param date
     */
    public void writeLastClosePriceByDate(String date) {
        logger.info("更新【" + date + "】日，stock_transaction_data表的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_LAST_CLOSE_PRICE_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("【" + date + "】日，stock_transaction_data表的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段");
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的UP_DOWN字段
     * stock_transaction_data表的up_down字段已经在获取数据时就计算好了，所以现在这个方法用不着了。
     */
    public void writeUpDownByDate(String date) {
        logger.info("write stock close up down by date begin");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_UP_DOWN_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("write stock close up down by date finish");
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的EMA15，EMA26，DIF和DEA字段
     *
     * @param multithreading
     * @param date
     */
    public void writeMACDByDate(boolean multithreading, String date) {
        logger.info("开始计算所有股票在【" + date + "】的MACD数据");

        EntityManager entityManager = null;
        Query queryEma;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            queryEma = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_EMA_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            queryEma = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_EMA_BY_DATE(?)}");
        }
        queryEma.setParameter(1, date);
        queryEma.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
        } else {
            em.getTransaction().commit();
        }
        logger.info("所有股票在【" + date + "】的MACD指标中的ema计算完成");

        Query queryDif;
        if (multithreading) {
            entityManager.getTransaction().begin();
            queryDif = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_DIF_BY_DATE(?)}");
        } else {
            em.getTransaction().begin();
            queryDif = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_DIF_BY_DATE(?)}");
        }
        queryDif.setParameter(1, date);
        queryDif.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
        } else {
            em.getTransaction().commit();
        }
        logger.info("所有股票在【" + date + "】的MACD指标中的dif计算完成");

        Query queryDea;
        if (multithreading) {
            entityManager.getTransaction().begin();
            queryDea = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_DEA_BY_DATE(?)}");
        } else {
            em.getTransaction().begin();
            queryDea = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_DEA_BY_DATE(?)}");
        }
        queryDea.setParameter(1, date);
        queryDea.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
        } else {
            em.getTransaction().commit();
        }
        logger.info("所有股票在【" + date + "】的MACD指标中的dea计算完成");

        Query queryMacd;
        if (multithreading) {
            entityManager.getTransaction().begin();
            queryMacd = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_BY_DATE(?)}");
        } else {
            em.getTransaction().begin();
            queryMacd = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_BY_DATE(?)}");
        }
        queryMacd.setParameter(1, date);
        queryMacd.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }
        logger.info("所有股票在【" + date + "】的MACD指标中的macd计算完成");

        logger.info("所有股票在【" + date + "】的MACD数据计算完成");
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的TODAY_UP_DOWN_PERCENTAGE字段
     */
    public void calUpDownPercentageByDate(String date) {
        logger.info("write up down percentage by date begin");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_UP_DOWN_PERCENTAGE_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("write up down percentage by date finish");
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的FIVE_DAY_VOLATILITY，TEN_DAY_VOLATILITY和TWENTY_DAY_VOLATILITY字段
     */
    public void calVolatilityByDate(String date) {
        logger.info("write volatility by date begin");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLATILITY_BY_DATE(?)}");
        query.setParameter(1, date);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("write volatility by date finish");
    }

    /**
     * 更新stock_transaction_data表中某一日的KD指标
     */
    public void writeKDByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的KD指标");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_BY_DATE_RSV(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_BY_DATE_RSV(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
        } else {
            em.getTransaction().commit();
        }
        logger.info("更新stock_transaction_data表中日期【" + date + "】的KD指标中的RSV完成");

        Query kQuery;
        if (multithreading) {
            entityManager.getTransaction().begin();
            kQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_BY_DATE_K(?)}");
        } else {
            em.getTransaction().begin();
            kQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_BY_DATE_K(?)}");
        }
        kQuery.setParameter(1, date);
        kQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
        } else {
            em.getTransaction().commit();
        }
        logger.info("更新stock_transaction_data表中日期【" + date + "】的KD指标中的K完成");

        Query dQuery;
        if (multithreading) {
            entityManager.getTransaction().begin();
            dQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_BY_DATE_D(?)}");
        } else {
            em.getTransaction().begin();
            dQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_BY_DATE_D(?)}");
        }
        dQuery.setParameter(1, date);
        dQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }
        logger.info("更新stock_transaction_data表中日期【" + date + "】的KD指标中的D完成");

        logger.info("更新stock_transaction_data表中日期【" + date + "】的KD指标完成");
    }

    /**
     * 更新stock_transaction_data表中某一日的HA_OPEN_PRICE、HA_CLOSE_PRICE、HA_HIGHEST_PRICE、HA_LOWEST_PRICE
     */
    public void writeHaByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的HA_OPEN_PRICE、HA_CLOSE_PRICE、HA_HIGHEST_PRICE、HA_LOWEST_PRICE指标");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_HA_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_HA_BY_DATE(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中日期【" + date + "】的HA_OPEN_PRICE、HA_CLOSE_PRICE、HA_HIGHEST_PRICE、HA_LOWEST_PRICE指标完成");
    }

    /**
     * 更新stock_transaction_data表中某一日的boll相关字段
     */
    public void writeBollByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的boll相关字段");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.CAL_BOLL_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_BOLL_BY_DATE(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中日期【" + date + "】的boll相关字段");
    }

    /**
     * 更新stock_transaction_data表中某一日的bias相关字段
     */
    public void writeBiasByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的bias相关字段");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_BIAS_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_BIAS_BY_DATE(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中日期【" + date + "】的bias相关字段");
    }

    /**
     * 更新stock_transaction_data表中某一日的方差相关字段
     */
    public void writeVarianceByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的方差相关字段");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_VARIANCE_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_VARIANCE_BY_DATE(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中日期【" + date + "】的方差相关字段");
    }

    /**
     * 更新stock_transaction_data_all表中某一日的成交量移动平均线相关字段
     */
    public void writeVolumeMaByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的成交量移动平均线相关字段");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_VOLUME_MA_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_VOLUME_MA_BY_DATE(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中日期【" + date + "】的成交量移动平均线相关字段");
    }

    /**
     * 更新stock_transaction_data_all表中某一日的成交额移动平均线相关字段
     */
    public void writeTurnoverMaByDate(boolean multithreading, String date) {
        logger.info("更新stock_transaction_data表中日期【" + date + "】的成交额移动平均相关字段");

        EntityManager entityManager = null;
        Query rsvQuery;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            rsvQuery = entityManager.createNativeQuery("{call pkg_stock_transaction_data.WRITE_TURNOVER_MA_BY_DATE(?)}");
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            rsvQuery = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_TURNOVER_MA_BY_DATE(?)}");
        }
        rsvQuery.setParameter(1, date);
        rsvQuery.executeUpdate();
        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("更新stock_transaction_data表中日期【" + date + "】的成交额移动平均相关字段");
    }

    /*********************************************************************************************************************
     *
     * 									                             根据每日数据更新图表
     *
     *********************************************************************************************************************/
    /**
     * 根据开始日期和结束日期，获取其中的所有交易日期
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @param tenYear
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<String> getDateByCondition(boolean multithreading, String beginDate, String endDate, boolean tenYear) {
        logger.info("根据开始日期和结束日期，获取其中的所有交易日期");

        List<String> list;
        String queryString;
        if (tenYear) {
            queryString =
                    "select distinct to_char(date,'yyyy-mm-dd') as date from StockTransactionDataAll t "
                            + "where date between to_date(" + beginDate + ",'yyyy-mm-dd') and to_date(" + endDate
                            + ",'yyyy-mm-dd')" + " order by date asc";
        } else {
            queryString =
                    "select distinct to_char(date,'yyyy-mm-dd') as date from StockTransactionData t "
                            + "where date between to_date(" + beginDate + ",'yyyy-mm-dd') and to_date(" + endDate
                            + ",'yyyy-mm-dd')" + " order by date asc";
        }

        EntityManager entityManager = null;
        Query queryDateByCondition;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            queryDateByCondition = entityManager.createQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            queryDateByCondition = em.createQuery(queryString);
        }

        list = queryDateByCondition.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某段时间内，上证指数所有的交易日期
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<String> findDistinctDateBetweenDate(boolean multithreading, String beginDate, String endDate) {

        List<String> list;
        String queryString = new String("select distinct to_char(date,'yyyy-mm-dd') as date from StockIndex t where code='000001' and date " +
                "between to_date(" + beginDate + ",'yyyy-mm-dd') and to_date(" + endDate + ",'yyyy-mm-dd') order by date asc");

        EntityManager entityManager = null;
        Query queryDateByCondition;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            queryDateByCondition = entityManager.createQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            queryDateByCondition = em.createQuery(queryString);
        }

        list = queryDateByCondition.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某一日dif的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageDif(boolean multithreading, String date) {

        String dif;
        String queryDif = new String(
                "select sum(t.dif)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDif);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDif);
        }

        dif = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dif;
    }

    /**
     * 获取某一日dea的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageDea(boolean multithreading, String date) {

        String dea;
        String queryDea = new String(
                "select sum(t.dea)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDea);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDea);
        }

        dea = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dea;
    }

    /**
     * 获取某一日k的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageK(boolean multithreading, String date) {

        String dif;
        String queryDif = new String(
                "select sum(t.k)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDif);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDif);
        }

        dif = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dif;
    }

    /**
     * 获取某一日d的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageD(boolean multithreading, String date) {

        String dea;
        String queryDea = new String(
                "select sum(t.d)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDea);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDea);
        }

        dea = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dea;
    }

    /**
     * 获取某一日close_price的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageClosePrice(boolean multithreading, String date) {

        String dif;
        String queryDif = new String(
                "select sum(t.close_price)/count(t.code_) from stock_transaction_data_all t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDif);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDif);
        }

        dif = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dif;
    }

    /**
     * 获取某一日ha_close_price的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageHaClosePrice(boolean multithreading, String date) {

        String dif;
        String queryDif = new String(
                "select sum(t.ha_close_price)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDif);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDif);
        }

        dif = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dif;
    }

    /**
     * 获取某一日的total_market_value的总市值
     * @param multithreading
     * @param date
     * @return
     */
    @Override
    public Double getSumTotalMarketValue(boolean multithreading, String date) {
        Double averageTotalMarketValue;
        String averageTotalMarketValueSql = new String(
                "select sum(t.total_market_value) from stock_transaction_data_all t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(averageTotalMarketValueSql);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(averageTotalMarketValueSql);
        }

        averageTotalMarketValue = Double.valueOf(String.valueOf(query.getResultList().get(0)));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return averageTotalMarketValue;
    }

    /**
     * 获取某一日ha_open_price的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageHaOpenPrice(boolean multithreading, String date) {

        String dif;
        String queryDif = new String(
                "select sum(t.ha_open_price)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDif);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDif);
        }

        dif = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dif;
    }

    /**
     * 获取某一日MA5的平均值
     *
     * @param multithreading
     * @param date
     * @return
     */
    public String getAverageMA5(boolean multithreading, String date) {

        String dea;
        String queryDea = new String(
                "select sum(t.ma5)/count(t.code_) from stock_transaction_data t where t.date_=to_date('" + date + "','yyyy-mm-dd')");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryDea);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryDea);
        }

        dea = String.valueOf(query.getResultList().get(0));

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return dea;
    }

    /**
     * 获取从开始日期至结束日期，上证指数的所有交易日的日期
     *
     * @param multithreading
     * @param closeBeginDate
     * @param closeEndDate
     * @param indexCode
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<String> getDateByConditionForClose(boolean multithreading, String closeBeginDate, String closeEndDate, String indexCode) {

//		String localIndex;
//		if(IndexInfo.SZ_INDEX.getUrlParam().equals(index)){
//			localIndex=IndexInfo.SZ_INDEX.getUrlParam();
//		}else if(IndexInfo.SC_INDEX.getUrlParam().equals(index)){
//			localIndex=IndexInfo.SC_INDEX.getUrlParam();
//		}else if(IndexInfo.ZXB_INDEX.getUrlParam().equals(index)){
//			localIndex=IndexInfo.ZXB_INDEX.getUrlParam();
//		}else if(IndexInfo.CYB_INDEX.getUrlParam().equals(index)){
//			localIndex=IndexInfo.CYB_INDEX.getUrlParam();
//		}else{
//			localIndex=null;
//		}

        List<String> list = new ArrayList<String>();
        String queryString = new String("select distinct to_char(date,'yyyy-mm-dd') as date from StockIndex t where code=? and date " +
                "between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') order by date asc");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryClose = em.createQuery(queryString);
        queryClose.setParameter(1, indexCode);
        queryClose.setParameter(2, closeBeginDate);
        queryClose.setParameter(3, closeEndDate);
        list = queryClose.getResultList();
        em.getTransaction().commit();
        em.close();

        return list;
    }

    /**
     * 获取从开始日期至结束日期，每个交易日所有股票的平均价格（所有股票的收盘价之和/参加交易的股票的数量）
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @param codePrefixArray
     * @return
     */
    public List getAverageCloseWithDate(boolean multithreading, String beginDate, String endDate, boolean tenYear, String... codePrefixArray) {

        StringBuffer conditionStringBuffer = new StringBuffer();
        if (codePrefixArray.length == 1 && "all".equals(codePrefixArray[0])) {
            // 所有股票
            conditionStringBuffer.append("");
        } else if (codePrefixArray.length == 4) {
            // 沪市A股和科创版股票。由于科创版还没有指数，因此暂时将它算到沪市A股中
            conditionStringBuffer.append(" and (t.code_ like '").append(codePrefixArray[0])
                    .append("%'").append(" or t.code_ like '").append(codePrefixArray[1]).append("%'")
                    .append(" or t.code_ like '").append(codePrefixArray[2]).append("%'")
                    .append(" or t.code_ like '").append(ExchangeBoardInfo.KCB_PREFIX.getCodePrefixArray()[0])
                    .append("%')");
        } else if (codePrefixArray.length == 2) {
            // 深市A股或中小板股票
            conditionStringBuffer.append(" and (t.code_ like '").append(codePrefixArray[0])
                    .append("%'").append(" or t.code_ like '").append(codePrefixArray[1]).append("%')");
        } else if (codePrefixArray.length == 1 && !"all".equals(codePrefixArray[0])) {
            // 创业板股票
            conditionStringBuffer.append(" and (t.code_ like '").append(codePrefixArray[0])
                    .append("%')");
        }

        String queryClose;
        if (tenYear) {
            queryClose = new String(
                    "select * from (select t.date_,sum(t.close_price)/count(t.code_) from stock_transaction_data_all t " +
                            "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " + conditionStringBuffer.toString() +
                            "group by t.date_) o order by o.date_ asc");
        } else {
            queryClose = new String(
                    "select * from (select t.date_,sum(t.close_price)/count(t.code_) from stock_transaction_data_all t " +
                            "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " + conditionStringBuffer.toString() +
                            "group by t.date_) o order by o.date_ asc");
        }

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery(queryClose);
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        List list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        return list;
    }

	/*@SuppressWarnings("rawtypes")
	public List getAverageCloseWithDate(String beginDate,String endDate){
		logger.info("get stock close begin");
		
		String queryClose = new String(
				"select * from (select t.stock_date,sum(t.stock_close)/count(t.stock_code) from stock_moving_average t " +
				"where t.stock_date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
				"group by t.stock_date) o order by o.stock_date asc");
		em = JpaUtil.currentEntityManager();
		em.getTransaction().begin();
		Query query = em.createNativeQuery(queryClose);
		query.setParameter(1, beginDate);
		query.setParameter(2, endDate);
		List list=query.getResultList();
		em.getTransaction().commit();
		em.close();
		
		logger.info("get stock close finish");
		return list;
	}*/

    /**
     * 为创建28分化图表中的柱状图，获取某个指定日期时，UP_DOWN字段分别为1,-1和0的数量
     *
     * @param multithreading
     * @param date
     * @param upDown
     * @return
     */
    public int getUpDownNumberForBarChart(boolean multithreading, String date, UpDown upDown) {
        logger.info("get updown number for bar chart begin");

        int num;
        String queryClose = new String(
                "select count(*) from stock_transaction_data std where std.date_=to_date('" + date + "','yyyy-mm-dd') and std.up_down=" + upDown.getIndex());

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryClose);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryClose);
        }

        num = Integer.parseInt(query.getResultList().get(0).toString());

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        logger.info("get updown number for bar chart finish");
        return num;
    }

    /**
     * 获取从开始日期至结束日期内MACD处于金叉状态（dif>dea）的股票的比率
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public List getMACDGoldCrossStockRate(boolean multithreading, String beginDate, String endDate) {

        List<StockMovingAverage> list = new ArrayList<StockMovingAverage>();
        String queryString = new String("select t.date_, count(*)/("
                + "select count(*) from stock_transaction_data o where o.date_=t.date_"
                + ")*100 from stock_transaction_data t where t.dif>t.dea and t.date_ between to_date('" + beginDate + "','yyyy-mm-dd') and to_date('" + endDate + "','yyyy-mm-dd') group by t.date_ order by t.date_ desc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某一段时间内平均价格中的最大价格和最小价格
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    public List getMaxMinAverageCloseWeek(boolean multithreading, String beginDate, String endDate) {

        List list;
        String queryString = new String("select max(avg(t.close_price)),min(avg(t.close_price)) from stock_transaction_data_all t " +
                "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某一段时间内dif和dea的最大价格和最小价格
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List getMaxMinDifDea(boolean multithreading, String beginDate, String endDate) {

        List list = new ArrayList<String>();
        String queryString = new String("select max(avg(t.dif)),min(avg(t.dif)),max(avg(t.dea)),min(avg(t.dea)) from stock_transaction_data t " +
                "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某一段时间内k和d的最大价格和最小价格
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List getMaxMinKD(boolean multithreading, String beginDate, String endDate) {

        List list = new ArrayList<String>();
        String queryString = new String("select max(avg(t.k)),min(avg(t.k)),max(avg(t.d)),min(avg(t.d)) from stock_transaction_data t " +
                "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某一段时间内close_price和ma5的最大价格和最小价格
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List getMaxMinClosePriceAndMa5(boolean multithreading, String beginDate, String endDate) {

        List list = new ArrayList<String>();
        String queryString = new String("select max(avg(t.close_price)),min(avg(t.close_price)),max(avg(t.ma5)),min(avg(t.ma5)) from stock_transaction_data t " +
                "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 获取某一段时间内ha_close_price和ha_open_price的最大价格和最小价格
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List getMaxMinHaClosePriceAndHaOpenPrice(boolean multithreading, String beginDate, String endDate) {

        List list = new ArrayList<String>();
        String queryString = new String("select max(avg(t.ha_close_price)),min(avg(t.ha_close_price)),max(avg(t.ha_open_price)),min(avg(t.ha_open_price)) from stock_transaction_data t " +
                "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        list = query.getResultList();

        if (multithreading) {
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /*********************************************************************************************************************
     *
     * 									                            更新所有的数据
     *
     *********************************************************************************************************************/
    public void calculateMovingAverage() {
        logger.info("开始计算5日均线、10日均线、20日均线、60日均线、120日均线");

        em = JpaUtil.currentEntityManager();

        em.getTransaction().begin();
        Query queryFive = em.createNativeQuery("{call pkg_stock_transaction_data.Calculate_Five()}");
        queryFive.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算5日均线完成");

        em.getTransaction().begin();
        Query queryTen = em.createNativeQuery("{call pkg_stock_transaction_data.Calculate_Ten()}");
        queryTen.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算10日均线完成");

        em.getTransaction().begin();
        Query queryTwenty = em.createNativeQuery("{call pkg_stock_transaction_data.Calculate_Twenty()}");
        queryTwenty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算20日均线完成");

        em.getTransaction().begin();
        Query querySixty = em.createNativeQuery("{call pkg_stock_transaction_data.Calculate_Sixty()}");
        querySixty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算60日均线完成");

        em.getTransaction().begin();
        Query queryOneHundredTwenty = em.createNativeQuery("{call pkg_stock_transaction_data.Calculate_OneHundredTwenty()}");
        queryOneHundredTwenty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算120日均线完成");

        em.getTransaction().begin();
        Query queryTwoHundredFifty = em.createNativeQuery("{call pkg_stock_transaction_data.Calculate_TwoHundredFifty()}");
        queryTwoHundredFifty.executeUpdate();
        em.getTransaction().commit();
        em.close();
        logger.info("计算250日均线完成");
    }

    public void calculateUpDownPercentage() {
        logger.info("开始计算change_range_ex_right字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_CHANGE_RANGE_EX_RIGHT()}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("change_range_ex_right字段计算完成");
    }

    public void calculateVolatility() {
        logger.info("calculate volatility begin");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.CALCULATE_VOLATILITY()}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("calculate volatility finish");
    }

    /**
     * 计算所有股票的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段
     */
    public void writeLastClosePrice() {
        logger.info("计算所有股票的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_LAST_CLOSE_PRICE()}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("计算所有股票的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段完成");
    }

    /**
     * stock_transaction_data表的up_down字段已经在获取数据时就计算好了，所以现在这个方法用不着了。
     */
    public void writeUpDown() {
        logger.info("write stock close up down begin");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_UP_DOWN()}");
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("write stock close up down finish");
    }

    public void writeMACD() {
        logger.info("开始计算所有股票的MACD");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryInit = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_INIT()}");
        queryInit.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票的MACD中的初始化数据计算完成");

        em.getTransaction().begin();
        Query queryEma = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_EMA()}");
        queryEma.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票的MACD中的ema数据计算完成");

        em.getTransaction().begin();
        Query queryDif = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_DIF()}");
        queryDif.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票的MACD中的dif数据计算完成");

        em.getTransaction().begin();
        Query queryDea = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD_DEA()}");
        queryDea.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票的MACD中的dea数据计算完成");

        em.getTransaction().begin();
        Query queryMacd = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_MACD()}");
        queryMacd.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票的MACD中的macd数据计算完成");

        em.close();

        logger.info("所有股票的MACD计算完成");
    }

    public void writeKD() {
        logger.info("开始计算所有股票，日线级别的KD");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryInit = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_INIT()}");
        queryInit.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票，日线级别KD中的初始化数据计算完成");

        em.getTransaction().begin();
        Query queryEma = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_RSV()}");
        queryEma.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票，日线级别KD中的RSV数据计算完成");

        em.getTransaction().begin();
        Query queryDif = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_K()}");
        queryDif.executeUpdate();
        em.getTransaction().commit();
        logger.info("所有股票，日线级别KD中的K数据计算完成");

        em.getTransaction().begin();
        Query queryDea = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_KD_D()}");
        queryDea.executeUpdate();
        em.getTransaction().commit();
        em.close();
        logger.info("所有股票，日线级别KD中的D数据计算完成");

        logger.info("所有股票，日线级别的KD计算完成");
    }

    public void writeHa() {
        logger.info("开始计算所有股票，日线级别的HA_OPEN_PRICE、HA_CLOSE_PRICE、HA_HIGHEST_PRICE、HA_LOWEST_PRICE");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryInit = em.createNativeQuery("{call pkg_stock_transaction_data.write_ha()}");
        queryInit.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("所有股票，日线级别的HA_OPEN_PRICE、HA_CLOSE_PRICE、HA_HIGHEST_PRICE、HA_LOWEST_PRICE计算完成");
    }

    public void writeBoll() {
        logger.info("开始计算所有股票，日线级别的boll相关字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryInit = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_BOLL()}");
        queryInit.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("计算所有股票，日线级别的boll相关字段完成");
    }

    public void writeBias() {
        logger.info("开始计算所有股票，日线级别的bias相关字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryInit = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_BIAS()}");
        queryInit.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("计算所有股票，日线级别的bias相关字段完成");
    }

    public void writeVariance() {
        logger.info("开始计算所有股票，日线级别的方差相关字段");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query queryInit = em.createNativeQuery("{call pkg_stock_transaction_data.WRITE_VARIANCE()}");
        queryInit.executeUpdate();
        em.getTransaction().commit();
        em.close();

        logger.info("计算所有股票，日线级别的方差相关字段完成");
    }

    public void writeVolumeMa() {
        logger.info("开始计算成交量5日均线、10日均线、20日均线、60日均线、120日均线");

        em = JpaUtil.currentEntityManager();

        em.getTransaction().begin();
        Query queryFive = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLUME_MA5()}");
        queryFive.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交量5日均线完成");

        em.getTransaction().begin();
        Query queryTen = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLUME_MA10()}");
        queryTen.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交量10日均线完成");

        em.getTransaction().begin();
        Query queryTwenty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLUME_MA20()}");
        queryTwenty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交量20日均线完成");

        em.getTransaction().begin();
        Query querySixty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLUME_MA60()}");
        querySixty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交量60日均线完成");

        em.getTransaction().begin();
        Query queryOneHundredTwenty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLUME_MA120()}");
        queryOneHundredTwenty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交量120日均线完成");

        em.getTransaction().begin();
        Query queryTwoHundredFifty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_VOLUME_MA250()}");
        queryTwoHundredFifty.executeUpdate();
        em.getTransaction().commit();
        em.close();
        logger.info("计算成交量250日均线完成");
    }

    public void writeTurnoverMa() {
        logger.info("开始计算成交额5日均线、10日均线、20日均线、60日均线、120日均线");

        em = JpaUtil.currentEntityManager();

        em.getTransaction().begin();
        Query queryFive = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_TURNOVER_MA5()}");
        queryFive.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交额5日均线完成");

        em.getTransaction().begin();
        Query queryTen = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_TURNOVER_MA10()}");
        queryTen.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交额10日均线完成");

        em.getTransaction().begin();
        Query queryTwenty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_TURNOVER_MA20()}");
        queryTwenty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交额20日均线完成");

        em.getTransaction().begin();
        Query querySixty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_TURNOVER_MA60()}");
        querySixty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交额60日均线完成");

        em.getTransaction().begin();
        Query queryOneHundredTwenty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_TURNOVER_MA120()}");
        queryOneHundredTwenty.executeUpdate();
        em.getTransaction().commit();
        logger.info("计算成交额120日均线完成");

        em.getTransaction().begin();
        Query queryTwoHundredFifty = em.createNativeQuery("{call pkg_stock_transaction_data.CAL_TURNOVER_MA250()}");
        queryTwoHundredFifty.executeUpdate();
        em.getTransaction().commit();
        em.close();
        logger.info("计算成交额250日均线完成");
    }

    /**
     * 获取某一日多头排列的股票
     *
     * @param date
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public List getBullRank(String date) {
        logger.info("get bull rank begin");

        List<StockMovingAverage> list = new ArrayList<StockMovingAverage>();
        String stringBullRank = new String(
                "select distinct t from StockMovingAverage t "
                        + "where t.stockClose>=t.five and t.stockClose>=t.ten and t.stockClose>=t.twenty and t.stockClose>=t.sixty and t.stockClose>=t.oneHundredTwenty "
                        + "and t.five>=t.ten and t.five>=t.twenty and t.five>=t.sixty and t.five>=t.oneHundredTwenty "
                        + "and t.ten>=t.twenty and t.ten>=t.sixty and t.ten>=t.oneHundredTwenty "
                        + "and t.twenty>=t.sixty and t.twenty>=t.oneHundredTwenty "
                        + "and t.sixty>=t.oneHundredTwenty "
                        + "and t.stockDate=to_date(" + date + ",'yyyy-mm-dd')");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createQuery(stringBullRank);
        list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        logger.info("get bull rank finish");
        return list;
    }

    /**
     * 获取某一日空头排列的股票
     *
     * @param date
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public List getShortOrder(String date) {
        logger.info("get short order begin");

        List<StockMovingAverage> list = new ArrayList<StockMovingAverage>();
        String queryString = new String(
                "select distinct t from StockMovingAverage t "
                        + "where t.stockClose<=t.five and t.stockClose<=t.ten and t.stockClose<=t.twenty and t.stockClose<=t.sixty and t.stockClose<=t.oneHundredTwenty "
                        + "and t.five<=t.ten and t.five<=t.twenty and t.five<=t.sixty and t.five<=t.oneHundredTwenty "
                        + "and t.ten<=t.twenty and t.ten<=t.sixty and t.ten<=t.oneHundredTwenty "
                        + "and t.twenty<=t.sixty and t.twenty<=t.oneHundredTwenty "
                        + "and t.sixty<=t.oneHundredTwenty "
                        + "and t.stockDate=to_date(" + date + ",'yyyy-mm-dd')");
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createQuery(queryString);
        list = query.getResultList();
        em.getTransaction().commit();
        em.close();

        logger.info("get short order finish");
        return list;
    }

    /**
     * 获取某段时间内，每个交易日的多头排列的股票的数量
     *
     * @param beginDate
     * @param endDate
     * @param tenYear
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public List getBullRankNumberWithinDate(String beginDate, String endDate, boolean tenYear) {
        logger.info("获取某段时间内，每个交易日的多头排列的股票的数量");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        // 获取某一日多头排列的股票数量
        List bullRankNumber = new ArrayList();

        String stringBullRank;
        if (tenYear) {
            stringBullRank = new String("select to_char(t2.date_, 'yyyy-mm-dd'), count(*) as num from(select * from stock_transaction_data_all t " +
                    "where t.date_ between to_date(" + beginDate + ",'yyyy-mm-dd') " +
                    "and to_date(" + endDate + ",'yyyy-mm-dd') " +
                    "and t.close_price>=t.ma5 and t.close_price>=t.ma10 and t.close_price>=t.ma20 and t.close_price>=t.ma60 " +
                    "and t.close_price>=t.ma120 and t.ma5>=t.ma10 and t.ma5>=t.ma20 and t.ma5>=t.ma60 " +
                    "and t.ma5>=t.ma120 and t.ma10>=t.ma20 and t.ma10>=t.ma60 and t.ma10>=t.ma120 " +
                    "and t.ma20>=t.ma60 and t.ma20>=t.ma120 and t.ma60>=t.ma120) t2 " +
                    "group by t2.date_ order by t2.date_ asc");
        } else {
            stringBullRank = new String("select to_char(t2.date_, 'yyyy-mm-dd'), count(*) as num from(select * from stock_transaction_data t " +
                    "where t.date_ between to_date(" + beginDate + ",'yyyy-mm-dd') " +
                    "and to_date(" + endDate + ",'yyyy-mm-dd') " +
                    "and t.close_price>=t.ma5 and t.close_price>=t.ma10 and t.close_price>=t.ma20 and t.close_price>=t.ma60 " +
                    "and t.close_price>=t.ma120 and t.ma5>=t.ma10 and t.ma5>=t.ma20 and t.ma5>=t.ma60 " +
                    "and t.ma5>=t.ma120 and t.ma10>=t.ma20 and t.ma10>=t.ma60 and t.ma10>=t.ma120 " +
                    "and t.ma20>=t.ma60 and t.ma20>=t.ma120 and t.ma60>=t.ma120) t2 " +
                    "group by t2.date_ order by t2.date_ asc");
        }

        Query query = em.createNativeQuery(stringBullRank);
        bullRankNumber = query.getResultList();
        em.clear();

        em.getTransaction().commit();
        em.close();

        return bullRankNumber;
    }

    /**
     * 获取某段时间内，每个交易日的空头排列的股票的数量
     *
     * @param beginDate
     * @param endDate
     * @param tenYear
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public List getShortOrderNumberWithinDate(String beginDate, String endDate, boolean tenYear) {
        logger.info("获取某段时间内，每个交易日的空头排列的股票的数量");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        // 获取某一日空头排列的股票数量
        List shortOrderNumber = new ArrayList();

        String stringShortOrder;
        if (tenYear) {
            stringShortOrder = new String("select to_char(t2.date_, 'yyyy-mm-dd'), count(*) as num from(select * from stock_transaction_data_all t " +
                    "where t.date_ between to_date(" + beginDate + ",'yyyy-mm-dd') " +
                    "and to_date(" + endDate + ",'yyyy-mm-dd') " +
                    "and t.close_price<=t.ma5 and t.close_price<=t.ma10 and t.close_price<=t.ma20 and t.close_price<=t.ma60 " +
                    "and t.close_price<=t.ma120 and t.ma5<=t.ma10 and t.ma5<=t.ma20 and t.ma5<=t.ma60 " +
                    "and t.ma5<=t.ma120 and t.ma10<=t.ma20 and t.ma10<=t.ma60 and t.ma10<=t.ma120 " +
                    "and t.ma20<=t.ma60 and t.ma20<=t.ma120 and t.ma60<=t.ma120) t2 " +
                    "group by t2.date_ order by t2.date_ asc");
        } else {
            stringShortOrder = new String("select to_char(t2.date_, 'yyyy-mm-dd'), count(*) as num from(select * from stock_transaction_data t " +
                    "where t.date_ between to_date(" + beginDate + ",'yyyy-mm-dd') " +
                    "and to_date(" + endDate + ",'yyyy-mm-dd') " +
                    "and t.close_price<=t.ma5 and t.close_price<=t.ma10 and t.close_price<=t.ma20 and t.close_price<=t.ma60 " +
                    "and t.close_price<=t.ma120 and t.ma5<=t.ma10 and t.ma5<=t.ma20 and t.ma5<=t.ma60 " +
                    "and t.ma5<=t.ma120 and t.ma10<=t.ma20 and t.ma10<=t.ma60 and t.ma10<=t.ma120 " +
                    "and t.ma20<=t.ma60 and t.ma20<=t.ma120 and t.ma60<=t.ma120) t2 " +
                    "group by t2.date_ order by t2.date_ asc");
        }

        Query query = em.createNativeQuery(stringShortOrder);
        shortOrderNumber = query.getResultList();
        em.clear();

        em.getTransaction().commit();
        em.close();

        return shortOrderNumber;
    }

    /**
     * 获取某一段时间内股票涨停或跌停家数
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @param rate
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public List getStockLimitUpAndDownNumber(boolean multithreading, String beginDate, String endDate, double rate) {
        logger.info("get stock limit up and dwon number begin");

        // 用于记录某一段时间内股票涨停或跌停家数
        List limitUpDwonNumberList;

        StringBuffer limitUpDownNumberString = new StringBuffer("select t.date_,count(t.code_) " +
                "from stock_transaction_data t where t.date_ between to_date(?,'yyyy-mm-dd') " +
                "and to_date(?,'yyyy-mm-dd') and t.change_range");
        if (rate > 0) {
            limitUpDownNumberString.append(">=" + rate);
        } else {
            limitUpDownNumberString.append("<=" + rate);
        }
        limitUpDownNumberString.append(" group by t.date_ order by t.date_ asc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(limitUpDownNumberString.toString());
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(limitUpDownNumberString.toString());
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        limitUpDwonNumberList = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.clear();
            em.getTransaction().commit();
            em.close();
        }

        logger.info("get stock limit up and dwon number finish");
        return limitUpDwonNumberList;
    }

    /**
     * STOCK_TRANSACTION_DATA表中，某个交易日的记录
     *
     * @param date
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<StockTransactionData> getStocksByDate(String date) {
        logger.info("从STOCK_TRANSACTION_DATA表中，获取日期为【" + date + "】的交易记录");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        // 用于记录某段交易日内STOCK_TRANSACTION_DATA表的记录
        List<StockTransactionData> stockTransactionDataList = new ArrayList<StockTransactionData>();

        StringBuffer stringBuffer = new StringBuffer("select t from StockTransactionData t where t.date=to_date(?,'yyyy-mm-dd')");

        Query query = em.createQuery(stringBuffer.toString());
        query.setParameter(1, date);
        stockTransactionDataList = query.getResultList();
        em.clear();

        em.getTransaction().commit();
        em.close();

        return stockTransactionDataList;
    }

    /**
     * 获取上证股票，深证股票，中小板股票和创业板股票日线级别平均涨跌
     *
     * @param multithreading
     * @param beginDate
     * @param endDate
     * @param indexPrefix
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List getStockBigBoardUpDownPercentage(boolean multithreading, String beginDate, String endDate, String indexPrefix) {
        logger.info("method getStockBigBoardUpDownPercentage begin");

        List stockBigBoardUpDownPercentageList;

        StringBuffer stockBigBoardUpDownPercentageString = new StringBuffer("select t.date," +
                "sum(t.changeRange)/count(*) from StockTransactionData t where t.code like ? " +
                "and t.date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') " +
                "group by t.date order by t.date desc");

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createQuery(stockBigBoardUpDownPercentageString.toString());
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createQuery(stockBigBoardUpDownPercentageString.toString());
        }

        query.setParameter(1, indexPrefix);
        query.setParameter(2, beginDate);
        query.setParameter(3, endDate);
        stockBigBoardUpDownPercentageList = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.clear();
            em.getTransaction().commit();
            em.close();
        }

        logger.info("method getStockBigBoardUpDownPercentage finish");
        return stockBigBoardUpDownPercentageList;
    }

    /**
     * 根据开始日期和结束日期，删除表stock_transaction_data中的记录
     */
    public void deleteStockTransactionDataByDate(String beginDate, String endDate) {
        logger.info("根据开始日期【" + beginDate + "】和结束日期【" + endDate + "】，"
                + "删除表stock_transaction_data中的记录");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("delete from stock_transaction_data t "
                + "where t.date_ between to_date(?, 'yyyy-mm-dd') and to_date(?, 'yyyy-mm-dd')");
        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        query.executeUpdate();
        em.getTransaction().commit();
        em.close();
    }

    /*********************************************************************************************************************
     *
     * 									                            ModelMain类过滤股票
     *
     *********************************************************************************************************************/
    /**
     * 根据date，查找StockTransactionData对象列表
     *
     * @param date
     * @return
     */
    public List<StockTransactionData> findByDate(String date) {
        logger.info("在表stock_transaction_data表中查找日期为【" + date + "】的记录");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        String queryString = "select t from StockTransactionData t where t.date = to_date(?, 'yyyy-mm-dd')";
        Query query = em.createQuery(queryString);
        query.setParameter(1, date);
        List<StockTransactionData> stockTransactionDataList = query.getResultList();

        em.getTransaction().commit();
        em.close();

        return stockTransactionDataList;
    }

    /**
     * 根据条件code、date，查找stock_transaction_data表，按降序排列，只取前rownum条记录
     *
     * @param code
     * @param date
     * @param rownum
     * @param multithreading
     * @return
     */
    public List<StockTransactionData> findByCodeAndDateOrderByDateDescLtqRownum(String code, String date, Integer rownum, boolean multithreading) {
        logger.info("根据条件code【" + code + "】、date【" + date + "】，"
                + "查找stock_transaction_data表，按降序排列，只取前rownum【" + rownum + "】条记录");

        String queryString = "select * from (select * from stock_transaction_data t "
                + "where t.code_=? and t.date_<=to_date(?, 'yyyy-mm-dd') order by t.date_ desc "
                + ") b "
                + "where rownum<=?";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(queryString, StockTransactionData.class);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(queryString, StockTransactionData.class);
        }

        query.setParameter(1, code);
        query.setParameter(2, date);
        query.setParameter(3, rownum);
        List<StockTransactionData> stockTransactionDataList = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return stockTransactionDataList;
    }

    /**
     * 根据开始日期和结束日期，查找中间的日期，并去重
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    @Override
    public List<String> findDistinctDateBetweenBeginDateAndEndDate(boolean multithreading, String beginDate,
                                                                   String endDate) {
        logger.info("根据开始日期【" + beginDate + "】和结束日期【" + endDate + "】，查找中间的日期，并去重");

        String sql = "select distinct b.date_ from ( "
                + "select to_char(t.date_, 'yyyy-mm-dd') date_ from stock_transaction_data_all t "
                + "where t.date_ between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd') order by t.date_ asc) b "
                + "order by b.date_ asc";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(sql);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sql);
        }

        query.setParameter(1, beginDate);
        query.setParameter(2, endDate);
        List<String> list = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return list;
    }

    /**
     * 从stock_index表中查找某个交易日之前的日期
     *
     * @param multithreading
     * @param date
     * @return
     */
    public Date findPreviousDateByDate(boolean multithreading, String date) {
        logger.info("从stock_index表中查找某个交易日【" + date + "】之前的日期");

        String sql = "select * from( " +
                "select distinct t.date_ " +
                "from stock_transaction_data_all t " +
                "where t.date_<to_date(?,'yyyy-mm-dd') " +
                "order by t.date_ desc) t1 " +
                "where rownum<=1";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(sql);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sql);
        }

        query.setParameter(1, date);
        Date resultDate = (Date) query.getSingleResult();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return resultDate;
    }

    /**
     * 获取当前日期和前一日的平均dif和平均dea
     *
     * @param multithreading
     * @param currentDate
     * @param previousDate
     * @return
     */
    public List<BaseCurrentDataAndPreviousDateAverage> getAverageDifDeaByCurrentDateAndPreviousDate(boolean multithreading, final String currentDate, final String previousDate) {
        logger.info("开始获取当前日期【" + currentDate + "】和前一日【" + previousDate + "】的平均dif和平均dea");

//		String sql = "select ? currentDate, " +
//				"(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageDif, " +
//				"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageDea, " +
//				"? previousDate, " +
//				"(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageDif, " +
//				"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageDea, " +
//				"case when " +
//						"(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 1 " +
//					"when (select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 2 " +
//					"end goldCrossOrDeadCross " +
//				"from dual";

        String sql = "select ? currentDate, " +
//				"(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) + " +
//				"(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) / 2 averageDifDea, " +
                "case when " +
                "(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 1 " +
                "when (select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 2 " +
                "end goldCrossOrDeadCross, " +
                "null successRateOrPercentage," +
                "null shippingSpace, " +
                "case when " +
                "(select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.MACD_GOLD_CROSS + " " +
                "when (select avg(t1.dif) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.dea) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.MACD_DEAD_CROSS + " " +
                "end filterMethod " +
                "from dual";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        }

        query.setParameter(1, currentDate);
        query.setParameter(2, currentDate);
        query.setParameter(3, currentDate);
        query.setParameter(4, currentDate);
        query.setParameter(5, currentDate);
        query.setParameter(6, currentDate);
        query.setParameter(7, currentDate);
        query.setParameter(8, currentDate);
        query.setParameter(9, currentDate);
//		query.setParameter(10, currentDate);
//		query.setParameter(11, previousDate);
//		query.setParameter(12, previousDate);
//		query.setParameter(13, currentDate);
//		query.setParameter(14, currentDate);
        List<BaseCurrentDataAndPreviousDateAverage> currentDateAndPreviousDateAverageDifDeaList = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return currentDateAndPreviousDateAverageDifDeaList;
    }

    /**
     * 获取当前日期和前一日的平均close_price和平均ma5
     *
     * @param multithreading
     * @param currentDate
     * @param previousDate
     * @return
     */
    public List<BaseCurrentDataAndPreviousDateAverage> getAverageClosePriceMa5ByCurrentDateAndPreviousDate(boolean multithreading, final String currentDate, final String previousDate) {
        logger.info("开始获取当前日期【" + currentDate + "】和前一日【" + previousDate + "】的平均close_price和平均ma5");

//		String sql = "select ? currentDate, " +
//				"(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageClosePrice, " +
//				"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageMa5, " +
//				"? previousDate, " +
//				"(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageClosePrice, " +
//				"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageMa5, " +
//					"case when " +
//						"(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 1 " +
//					"when (select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 2 " +
//					"end goldCrossOrDeadCross " +
//				"from dual";

        String sql = "select ? currentDate, " +
//				"(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) + " +
//				"(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) / 2 averageClosePriceMa5, " +
                "case when " +
                "(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 1 " +
                "when (select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 2 " +
                "end goldCrossOrDeadCross, " +
                "null successRateOrPercentage," +
                "null shippingSpace, " +
                "case when " +
                "(select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.CLOSE_PRICE_GOLD_CROSS_MA + " " +
                "when (select avg(t1.close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.ma5) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.CLOSE_PRICE_DEAD_CROSS_MA + " " +
                "end filterMethod " +
                "from dual";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        }

        query.setParameter(1, currentDate);
        query.setParameter(2, currentDate);
        query.setParameter(3, currentDate);
        query.setParameter(4, currentDate);
        query.setParameter(5, currentDate);
        query.setParameter(6, currentDate);
        query.setParameter(7, currentDate);
        query.setParameter(8, currentDate);
        query.setParameter(9, currentDate);
//		query.setParameter(10, currentDate);
//		query.setParameter(11, previousDate);
//		query.setParameter(12, previousDate);
//		query.setParameter(13, currentDate);
//		query.setParameter(14, currentDate);
        List<BaseCurrentDataAndPreviousDateAverage> currentDateAndPreviousDateAverageClosePriceMa5List = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return currentDateAndPreviousDateAverageClosePriceMa5List;
    }

    /**
     * 获取当前日期和前一日的平均ha_close_price和平均ha_open_price
     *
     * @param multithreading
     * @param currentDate
     * @param previousDate
     * @return
     */
    public List<BaseCurrentDataAndPreviousDateAverage> getAverageHaClosePriceHaOpenPriceByCurrentDateAndPreviousDate(boolean multithreading, final String currentDate, final String previousDate) {
        logger.info("开始获取当前日期【" + currentDate + "】和前一日【" + previousDate + "】的平均ha_close_price和平均ha_open_price");

//		String sql = "select ? currentDate, " +
//				"(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageHaClosePrice, " +
//				"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageHaOpenPrice, " +
//				"? previousDate, " +
//				"(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageHaClosePrice, " +
//				"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageHaOpenPrice, " +
//				"case when " +
//						"(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 1 " +
//					"when (select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 2 " +
//				"end upDownOrDownUp " +
//				"from dual";

        String sql = "select ? currentDate, " +
//				"(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) + " +
//				"(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) / 2 averageHaClosePriceHaOpenPrice, " +
                "case when " +
                "(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 1 " +
                "when (select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 2 " +
                "end goldCrossOrDeadCross, " +
                "null successRateOrPercentage," +
                "null shippingSpace, " +
                "case when " +
                "(select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.HEI_KIN_ASHI_UP_DOWN + " " +
                "when (select avg(t1.ha_close_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.ha_open_price) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.HEI_KIN_ASHI_DOWN_UP + " " +
                "end filterMethod " +
                "from dual";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        }

        query.setParameter(1, currentDate);
        query.setParameter(2, currentDate);
        query.setParameter(3, currentDate);
        query.setParameter(4, currentDate);
        query.setParameter(5, currentDate);
        query.setParameter(6, currentDate);
        query.setParameter(7, currentDate);
        query.setParameter(8, currentDate);
        query.setParameter(9, currentDate);
//		query.setParameter(10, currentDate);
//		query.setParameter(11, previousDate);
//		query.setParameter(12, previousDate);
//		query.setParameter(13, currentDate);
//		query.setParameter(14, currentDate);
        List<BaseCurrentDataAndPreviousDateAverage> currentDateAndPreviousDateAverageHaClosePriceHaOpenPriceList = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return currentDateAndPreviousDateAverageHaClosePriceHaOpenPriceList;
    }

    /**
     * 获取当前日期和前一日的平均k和平均d
     *
     * @param multithreading
     * @param currentDate
     * @param previousDate
     * @return
     */
    public List<BaseCurrentDataAndPreviousDateAverage> getAverageKDByCurrentDateAndPreviousDate(boolean multithreading, final String currentDate, final String previousDate) {
        logger.info("开始获取当前日期【" + currentDate + "】和前一日【" + previousDate + "】的平均k和平均d");

//		String sql = "select ? currentDate, " +
//				"(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageK, " +
//				"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) currentAverageD, " +
//				"? previousDate, " +
//				"(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageK, " +
//				"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) previousAverageD, " +
//				"case when " +
//						"(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 1 " +
//					"when (select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"> " +
//						"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"and " +
//						"(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//						"< " +
//						"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
//					"then 2 " +
//					"end goldCrossOrDeadCross " +
//				"from dual";

        String sql = "select ? currentDate, " +
//				"(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) + " +
//				"(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) / 2 averageKD, " +
                "case when " +
                "(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 1 " +
                "when (select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then 2 " +
                "end goldCrossOrDeadCross, " +
                "null successRateOrPercentage," +
                "null shippingSpace, " +
                "case when " +
                "(select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "> " +
                "(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.KD_GOLD_CROSS + " " +
                "when (select avg(t1.k) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "< " +
                "(select avg(t1.d) from stock_transaction_data_all t1 where t1.date_=to_date(?,'yyyy-mm-dd')) " +
                "then " + FilterMethod.KD_DEAD_CROSS + " " +
                "end filterMethod " +
                "from dual";

        EntityManager entityManager = null;
        Query query;
        if (multithreading) {
            entityManager = JpaUtil.newEntityManager();
            entityManager.getTransaction().begin();
            query = entityManager.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        } else {
            em = JpaUtil.currentEntityManager();
            em.getTransaction().begin();
            query = em.createNativeQuery(sql, BaseCurrentDataAndPreviousDateAverage.class);
        }

        query.setParameter(1, currentDate);
        query.setParameter(2, currentDate);
        query.setParameter(3, currentDate);
        query.setParameter(4, currentDate);
        query.setParameter(5, currentDate);
        query.setParameter(6, currentDate);
        query.setParameter(7, currentDate);
        query.setParameter(8, currentDate);
        query.setParameter(9, currentDate);
//		query.setParameter(10, currentDate);
//		query.setParameter(11, previousDate);
//		query.setParameter(12, previousDate);
//		query.setParameter(13, currentDate);
//		query.setParameter(14, currentDate);
        List<BaseCurrentDataAndPreviousDateAverage> currentDateAndPreviousDateAverageKDList = query.getResultList();

        if (multithreading) {
            entityManager.clear();
            entityManager.getTransaction().commit();
            entityManager.close();
        } else {
            em.getTransaction().commit();
            em.close();
        }

        return currentDateAndPreviousDateAverageKDList;
    }

    /*********************************************************************************************************************
     *
     * 									                            RealTransactionMain用到的方法
     *
     *********************************************************************************************************************/
    /**
     * 根据code和date，查找最近8日内的最高收盘价和最低收盘价
     *
     * @param code
     * @param date
     * @return
     */
    public Object findHighestAndLowestClosePriceByCodeAndDateInEightDay(String code, Date date) {
        logger.info("根据股票代码【" + code + "】和日期【" + date + "】，"
                + "查找最近8日内的最高收盘价和最低收盘价");

        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        Query query = em.createNativeQuery("select max(highest_price),min(lowest_price) " +
                "from (select * from stock_transaction_data_all t where t.code_=? and t.date_<? " +
                "order by t.date_ desc) " +
                "where rownum<=8");
        query.setParameter(1, code);
        query.setParameter(2, date);
        Object obj = query.getSingleResult();
        em.getTransaction().commit();
        em.close();

        return obj;
    }

    /*********************************************************************************************************************
     *
     * 									                       打印文本报告
     *
     *********************************************************************************************************************/
    /**
     * 查询波段操作的股票（牛市），并发送邮件
     *
     * @param date
     */
    @Override
    public void findStockInBullAndSendMail(String date, String mailHost, String mailTransportProtocol, String mailSmtpAuth, String mailUsername, String mailPassword, String mailSubject) {
        // 查询数据
        List<String> codeList = this.findStockInBull(date);

        // 发送邮件
        this.sendMail(codeList, mailHost, mailTransportProtocol, mailSmtpAuth, mailUsername, mailPassword, mailSubject);
    }

    /**
     * 打印波段操作的股票（熊市），并发送邮件
     *
     * @param date
     */
    @Override
    public void findStockInShortAndSendMail(String date, String mailHost, String mailTransportProtocol, String mailSmtpAuth, String mailUsername, String mailPassword, String mailSubject) {
        // 查询数据
        List<String> codeList = this.findStockInShort(date);

        // 发送邮件
        this.sendMail(codeList, mailHost, mailTransportProtocol, mailSmtpAuth, mailUsername, mailPassword, mailSubject);
    }

    /**
     * 查询波段操作的股票（牛市）
     * @param date
     * @return
     */
    @Override
    public List<String> findStockInBull(String date) {
        List<String> codeList = new ArrayList<>();
        Connection conn = getOracleConnection();
        CallableStatement csmt = null;
        ResultSet rs = null;

        logger.info("查询波段操作的股票（牛市）");
        try {
            csmt = conn.prepareCall("{call pkg_stock_transaction_data.FIND_STOCK_IN_BULL(?,?)}");
            csmt.setString(1, date);
            csmt.registerOutParameter(2, Types.ARRAY, "T_STOCK_RESULT_ARRAY");
            csmt.execute();
            Array array = csmt.getArray(2);
            Object object = array.getArray();
            Object[] objects = (Object[]) object;
            for (int i = 0; i < objects.length; i++) {
                STRUCT struct = (STRUCT) objects[i];
                Datum[] datas = struct.getOracleAttributes();
                codeList.add(String.valueOf(datas[0]));
//                System.out.println(datas[0]);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                csmt.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return codeList;
    }

    /**
     * 查询波段操作的股票（熊市）
     * @param date
     * @return
     */
    @Override
    public List<String> findStockInShort(String date) {
        List<String> codeList = new ArrayList<>();
        Connection conn = getOracleConnection();
        CallableStatement csmt = null;
        ResultSet rs = null;

        logger.info("查询波段操作的股票（熊市）");
        try {
            csmt = conn.prepareCall("{call pkg_stock_transaction_data.find_stock_in_short(?,?)}");
            csmt.setString(1, date);
            csmt.registerOutParameter(2, Types.ARRAY, "T_STOCK_RESULT_ARRAY");
            csmt.execute();
            Array array = csmt.getArray(2);
            Object object = array.getArray();
            Object[] objects = (Object[]) object;
            for (int i = 0; i < objects.length; i++) {
                STRUCT struct = (STRUCT) objects[i];
                Datum[] datas = struct.getOracleAttributes();
                codeList.add(String.valueOf(datas[0]));
//                System.out.println(datas[0]);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                csmt.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return codeList;
    }

    /**
     * 发送邮件
     * @param codeList
     * @param mailHost
     * @param mailTransportProtocol
     * @param mailSmtpAuth
     * @param mailUsername
     * @param mailPassword
     * @param mailSubject
     */
    @Override
    public void sendMail(List<String> codeList, String mailHost, String mailTransportProtocol, String mailSmtpAuth, String mailUsername, String mailPassword, String mailSubject) {
        logger.info("开始发送邮件");

        Properties prop = new Properties();
        // 邮件服务器
        prop.setProperty("mail.host", mailHost);
        // 邮件发送协议
        prop.setProperty("mail.transport.protocol", mailTransportProtocol);
        // 需要验证用户名密码
        prop.setProperty("mail.smtp.auth", mailSmtpAuth);

        // 打印code
        if (null != codeList && codeList.size() > 0){
            for (String code: codeList){
                System.out.println(code);
            }
        }

        Transport ts = null;
        try {
            //使用JavaMail发送邮件的5个步骤
            //1.txt、创建定义整个应用程序所需的环境信息的Session对象
            javax.mail.Session session = javax.mail.Session.getDefaultInstance(prop, new Authenticator() {
                        public PasswordAuthentication getPasswordAuthentication() {
                            //发件人邮件用户名、授权码
                            return new PasswordAuthentication(mailUsername, mailPassword);
                        }
                    }
            );

            //开启Session的debug模式，这样就可以查看到程序发送Email的运行状态
            session.setDebug(true);

            //2、通过session得到transport对象
            ts = session.getTransport();

            //3、使用邮箱的用户名和授权码连上邮件服务器
            ts.connect(mailHost, mailUsername, mailPassword);

            //4，创建邮件
            //4-1.txt，创建邮件对象
            MimeMessage message = new MimeMessage(session);

            //4-2，指明邮件的发件人
            message.setFrom(new InternetAddress(mailUsername));

            //4-3，指明邮件的收件人
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(mailUsername));

            //4-4，邮件标题
            message.setSubject(mailSubject + "_" + DateUtil.dateToString(new Date()));

            //4-5，邮件文本内容
            StringBuffer stringBuffer = new StringBuffer();
            for (String code : codeList) {
                stringBuffer.append(code + "<br />");
            }
            message.setContent(stringBuffer.toString(), "text/html;charset=UTF-8");

            //4-6，发送邮件
            ts.sendMessage(message, message.getAllRecipients());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //5，关闭连接
            try {
                ts.close();
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }

        logger.info("发送邮件结束");
    }

    /*********************************************************************************************************************
     *
     * 									                            实验
     *
     *********************************************************************************************************************/
    @SuppressWarnings("null")
    public void test() {
        Connection conn = getOracleConnection();
        ResultSet rs = null;

        logger.info("test begin");
        try {
            CallableStatement csmt = conn.prepareCall("{call pkg_stock_transaction_data.SELECT_BULL_RANK_STOCK(?,?)}");
            csmt.setString(1, "20140825");
            csmt.registerOutParameter(2, OracleTypes.NUMBER);
            csmt.execute();
            String str = csmt.getString(2);
            logger.info("str: " + str);
            // rs = (ResultSet) csmt.getObject(2);
            while (rs.next()) {
                logger.info(rs.getObject(1) + " " + str);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        logger.info("test finish");
    }

    /*********************************************************************************************************************
     *
     * 									                            备份项目代码和数据库的表
     *
     *********************************************************************************************************************/
    /**
     * 持久化一个StockTransactionData对象
     *
     * @param stockTransactionData
     */
    public void save(StockTransactionData stockTransactionData) {
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();

        em.merge(stockTransactionData);

        em.getTransaction().commit();
        em.close();
    }

}
